package com.lambkit.core.http;

import com.lambkit.core.LambkitResult;

import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;

/**
 * @author yangyong(孤竹行)
 */
public interface IHttpContext {
    /**
     * Return HttpServletRequest. Do not use HttpServletRequest Object in constructor of ILambkitController
     */
    public IRequest getRequest();

    public void setHttpServletRequest(IRequest request);

    public void setHttpServletResponse(IResponse response);

    /**
     * Return HttpServletResponse. Do not use HttpServletResponse Object in constructor of ILambkitController
     */
    public IResponse getResponse();

    /**
     * Return HttpSession.
     */
    public ISession getSession();

    /**
     * Return HttpSession.
     * @param create a boolean specifying create HttpSession if it not exists
     */
    public ISession getSession(boolean create);

    /**
     * Get cookie object by cookie name.
     */
    public ICookie getCookieObject(String name);

    /**
     * Get all cookie objects.
     */
    public ICookie[] getCookieObjects();

    /**
     * Set Cookie to response.
     */
    void setCookie(ICookie cookie);

    ////////////////////////////////////////////request////////////////////////////////////
    public String getTarget();

    public void setTarget(String pathNew);

    public String getRawData();
    /**
     * Stores an attribute in this request
     * @param name a String specifying the name of the attribute
     * @param value the Object to be stored
     */
    void setAttr(String name, Object value);

    /**
     * Removes an attribute from this request
     * @param name a String specifying the name of the attribute to remove
     */
    void removeAttr(String name);

    /**
     * Stores attributes in this request, key of the map as attribute name and value of the map as attribute value
     * @param attrMap key and value as attribute of the map to be stored
     */
    void setAttrs(Map<String, Object> attrMap);

    /**
     * Returns the value of a request parameter as a String, or null if the parameter does not exist.
     * <p>
     * You should only use this method when you are sure the parameter has only one value. If the
     * parameter might have more than one value, use getParaValues(java.lang.String).
     * <p>
     * If you use this method with a multivalued parameter, the value returned is equal to the first
     * value in the array returned by getParameterValues.
     * @param name a String specifying the name of the parameter
     * @return a String representing the single value of the parameter
     */
    public String getPara(String name);

    /**
     * Returns the value of a request parameter as a String, or default value if the parameter does not exist.
     * @param name a String specifying the name of the parameter
     * @param defaultValue a String value be returned when the value of parameter is null
     * @return a String representing the single value of the parameter
     */
    public String getPara(String name, String defaultValue);

    /**
     * Returns the values of the request parameters as a Map.
     * @return a Map contains all the parameters name and value
     */
    public Map<String, String[]> getParaMap();

    /**
     * Returns an Enumeration of String objects containing the names of the parameters
     * contained in this request. If the request has no parameters, the method returns
     * an empty Enumeration.
     * @return an Enumeration of String objects, each String containing the name of
     * 			a request parameter; or an empty Enumeration if the request has no parameters
     */
    public Enumeration<String> getParaNames();

    /**
     * Returns an array of String objects containing all of the values the given request
     * parameter has, or null if the parameter does not exist. If the parameter has a
     * single value, the array has a length of 1.
     * @param name a String containing the name of the parameter whose value is requested
     * @return an array of String objects containing the parameter's values
     */
    public String[] getParaValues(String name);

    /**
     * Returns an array of Integer objects containing all of the values the given request
     * parameter has, or null if the parameter does not exist. If the parameter has a
     * single value, the array has a length of 1.
     * @param name a String containing the name of the parameter whose value is requested
     * @return an array of Integer objects containing the parameter's values
     */
    public Integer[] getParaValuesToInt(String name);

    public Long[] getParaValuesToLong(String name);

    /**
     * Returns an Enumeration containing the names of the attributes available to this request.
     * This method returns an empty Enumeration if the request has no attributes available to it.
     * @return an Enumeration of strings containing the names of the request's attributes
     */
    public Enumeration<String> getAttrNames();

    /**
     * Returns the value of the named attribute as an Object, or null if no attribute of the given name exists.
     * @param name a String specifying the name of the attribute
     * @return an Object containing the value of the attribute, or null if the attribute does not exist
     */
    public <T> T getAttr(String name);

    public <T> T getAttr(String name, T defaultValue);

    /**
     * Returns the value of the named attribute as an Object, or null if no attribute of the given name exists.
     * @param name a String specifying the name of the attribute
     * @return an String Object containing the value of the attribute, or null if the attribute does not exist
     */
    public String getAttrToStr(String name);

    /**
     * Returns the value of the named attribute as an Object, or null if no attribute of the given name exists.
     * @param name a String specifying the name of the attribute
     * @return an Integer Object containing the value of the attribute, or null if the attribute does not exist
     */
    public Integer getAttrToInt(String name);

    /**
     * Returns the value of the specified request header as a String.
     */
    public String getHeader(String name);

    /**
     * Returns the value of a request parameter and convert to Integer.
     * @param name a String specifying the name of the parameter
     * @return a Integer representing the single value of the parameter
     */
    public Integer getParaToInt(String name);

    /**
     * Returns the value of a request parameter and convert to Integer with a default value if it is null.
     * @param name a String specifying the name of the parameter
     * @return a Integer representing the single value of the parameter
     */
    public Integer getParaToInt(String name, Integer defaultValue);

    /**
     * Returns the value of a request parameter and convert to Long.
     * @param name a String specifying the name of the parameter
     * @return a Integer representing the single value of the parameter
     */
    public Long getParaToLong(String name);

    /**
     * Returns the value of a request parameter and convert to Long with a default value if it is null.
     * @param name a String specifying the name of the parameter
     * @return a Integer representing the single value of the parameter
     */
    public Long getParaToLong(String name, Long defaultValue);

    /**
     * Returns the value of a request parameter and convert to Boolean.
     * @param name a String specifying the name of the parameter
     * @return true if the value of the parameter is "true" or "1", false if it is "false" or "0", null if parameter is not exists
     */
    public Boolean getParaToBoolean(String name);

    /**
     * Returns the value of a request parameter and convert to Boolean with a default value if it is null.
     * @param name a String specifying the name of the parameter
     * @return true if the value of the parameter is "true" or "1", false if it is "false" or "0", default value if it is null
     */
    public Boolean getParaToBoolean(String name, Boolean defaultValue);

    /**
     * Get all para from url and convert to Boolean
     */
//    public Boolean getParaToBoolean() {
//        return toBoolean(getPara(), null);
//    }
//
//    /**
//     * Get para from url and conver to Boolean. The first index is 0
//     */
//    public Boolean getParaToBoolean(int index) {
//        return toBoolean(getPara(index), null);
//    }
//
//    /**
//     * Get para from url and conver to Boolean with default value if it is null.
//     */
//    public Boolean getParaToBoolean(int index, Boolean defaultValue) {
//        return toBoolean(getPara(index), defaultValue);
//    }

    /**
     * Returns the value of a request parameter and convert to Date.
     * @param name a String specifying the name of the parameter
     * @return a Date representing the single value of the parameter
     */
    public Date getParaToDate(String name);
    /**
     * Returns the value of a request parameter and convert to Date with a default value if it is null.
     * @param name a String specifying the name of the parameter
     * @return a Date representing the single value of the parameter
     */
    public Date getParaToDate(String name, Date defaultValue);

    ////////////////////////////////session//////////////////////////////////////////////

    /**
     * Return a Object from session.
     * @param key a String specifying the key of the Object stored in session
     */
    public <T> T getSessionAttr(String key);

    public <T> T getSessionAttr(String key, T defaultValue);

    /**
     * Store Object to session.
     * @param key a String specifying the key of the Object stored in session
     * @param value a Object specifying the value stored in session
     */
    void setSessionAttr(String key, Object value);

    /**
     * Remove Object in session.
     * @param key a String specifying the key of the Object stored in session
     */
    void removeSessionAttr(String key);

    /**
     * Get cookie value by cookie name.
     */
    public String getCookie(String name, String defaultValue);
    /**
     * Get cookie value by cookie name.
     */
    public String getCookie(String name);

    /**
     * Get cookie value by cookie name and convert to Integer.
     */
    public Integer getCookieToInt(String name);

    /**
     * Get cookie value by cookie name and convert to Integer.
     */
    public Integer getCookieToInt(String name, Integer defaultValue);

    /**
     * Get cookie value by cookie name and convert to Long.
     */
    public Long getCookieToLong(String name);

    /**
     * Get cookie value by cookie name and convert to Long.
     */
    public Long getCookieToLong(String name, Long defaultValue);

    /////////////////////////////////////////////cookie///////////////////////////////////////////

    ICookie createCookie(String name, String value);

    /**
     * Set Cookie.
     * @param name cookie name
     * @param value cookie value
     * @param maxAgeInSeconds -1: clear cookie when close browser. 0: clear cookie immediately.  n>0 : max age in n seconds.
     * @param isHttpOnly true if this cookie is to be marked as HttpOnly, false otherwise
     */
    void setCookie(String name, String value, int maxAgeInSeconds, Boolean isHttpOnly);
    /**
     * Set Cookie.
     * @param name cookie name
     * @param value cookie value
     * @param maxAgeInSeconds -1: clear cookie when close browser. 0: clear cookie immediately.  n>0 : max age in n seconds.
     */
    void setCookie(String name, String value, int maxAgeInSeconds);

    /**
     * Set Cookie to response.
     * @param name cookie name
     * @param value cookie value
     * @param maxAgeInSeconds -1: clear cookie when close browser. 0: clear cookie immediately.  n>0 : max age in n seconds.
     * @param path see Cookie.setPath(String)
     * @param isHttpOnly true if this cookie is to be marked as HttpOnly, false otherwise
     */
    void setCookie(String name, String value, int maxAgeInSeconds, String path, Boolean isHttpOnly);
    /**
     * Set Cookie to response.
     * @param name cookie name
     * @param value cookie value
     * @param maxAgeInSeconds -1: clear cookie when close browser. 0: clear cookie immediately.  n>0 : max age in n seconds.
     * @param path see Cookie.setPath(String)
     */
    void setCookie(String name, String value, int maxAgeInSeconds, String path);

    /**
     * Set Cookie to response.
     * @param name cookie name
     * @param value cookie value
     * @param maxAgeInSeconds -1: clear cookie when close browser. 0: clear cookie immediately.  n>0 : max age in n seconds.
     * @param path see Cookie.setPath(String)
     * @param domain the domain name within which this cookie is visible; form is according to RFC 2109
     * @param isHttpOnly true if this cookie is to be marked as HttpOnly, false otherwise
     */
    void setCookie(String name, String value, int maxAgeInSeconds, String path, String domain, Boolean isHttpOnly);

    void setCookie(String name, String value, int maxAgeInSeconds, String path, String domain, Boolean isHttpOnly, String sameSite);

    void doSetCookie(String name, String value, int maxAgeInSeconds, String path, String domain, Boolean isHttpOnly);
    /**
     * Remove Cookie.
     */
    void removeCookie(String name);

    /**
     * Remove Cookie.
     */
    void removeCookie(String name, String path);

    /**
     * Remove Cookie.
     */
    void removeCookie(String name, String path, String domain);

    /**
     * Keep all parameter's value except model value
     */
    void keepPara();

    /**
     * Keep parameter's value names pointed, model value can not be kept
     */
    void keepPara(String... names);

    /**
     * Convert para to special type and keep it
     */
    void keepPara(Class type, String name);

    void keepPara(Class type, String... names);

    /**
     * Return true if the para value is blank otherwise return false
     */
    public boolean isParaBlank(String paraName);

    /**
     * Return true if the para exists otherwise return false
     */
    public boolean isParaExists(String paraName);

    /**
     * 为了进一步省代码，创建与 setAttr(...) 功能一模一样的缩短版本 set(...)
     */
    void set(String attributeName, Object attributeValue);;

    // --- 以下是为了省代码，为 getPara 系列方法创建的缩短版本

    public String get(String name);

    public String get(String name, String defaultValue);

    public Integer getInt(String name);

    public Integer getInt(String name, Integer defaultValue);

    public Long getLong(String name);

    public Long getLong(String name, Long defaultValue);

    public Boolean getBoolean(String name);

    public Boolean getBoolean(String name, Boolean defaultValue);

    public Date getDate(String name);

    public Date getDate(String name, Date defaultValue);

    // --- 以下是将自定义参数解析方法/action/para1-para2-para3形式

    public void setUrlPara(String urlPara);

    public void setUrlPara(String urlPara, String separator);

    public void setUrlParaSeparator(String separator);

    public String getUrlPara();

    public String getUrlParaSeparator();

    /**
     * Get all para with separator char from url
     */
    public String getPara();

    /**
     * Get para from url. The index of first url para is 0.
     */
    public String getPara(int index);

    /**
     * Get para from url with default value if it is null or "".
     */
    public String getPara(int index, String defaultValue);

    /**
     * Get para from url and conver to Integer. The first index is 0
     */
    public Integer getParaToInt(int index);

    /**
     * Get para from url and conver to Integer with default value if it is null.
     */
    public Integer getParaToInt(int index, Integer defaultValue);

    /**
     * Get para from url and conver to Long.
     */
    public Long getParaToLong(int index);

    /**
     * Get para from url and conver to Long with default value if it is null.
     */
    public Long getParaToLong(int index, Long defaultValue);

    /**
     * Get all para from url and convert to Integer
     */
    public Integer getParaToInt();

    /**
     * Get all para from url and convert to Long
     */
    public Long getParaToLong();

    /**
     * Get all para from url and convert to Boolean
     */
    public Boolean getParaToBoolean();

    /**
     * Get para from url and conver to Boolean. The first index is 0
     */
    public Boolean getParaToBoolean(int index);

    /**
     * Get para from url and conver to Boolean with default value if it is null.
     */
    public Boolean getParaToBoolean(int index, Boolean defaultValue);

    // --- 以下是 getPara 系列中获取 urlPara 的缩短版本

	/* 为了让继承类可以使用名为 get 的 action 注掉此方法，可使用 get(-1) 来实现本方法的功能
	public String get() {
		return getPara();
	} */

    public String get(int index);

    public String get(int index, String defaultValue);

    public Integer getInt();

    public Integer getInt(int index);

    public Integer getInt(int index, Integer defaultValue);

    public Long getLong();

    public Long getLong(int index);

    public Long getLong(int index, Long defaultValue);

    public Boolean getBoolean();

    public Boolean getBoolean(int index);

    public Boolean getBoolean(int index, Boolean defaultValue);

    // --- bean

    public <T> T getBean(Class<T> beanClass);

    public <T> T getBean(Class<T> beanClass, boolean skipConvertError);

    public <T> T getBean(Class<T> beanClass, String beanName);

    public <T> T getBean(Class<T> beanClass, String beanName, boolean skipConvertError);

    // --- 文件参数获取方式
    public IUploadFile getFile(String name, String uploadPath);
    public IUploadFile getFile(String name, String uploadPath, long maxPostSize);

    public IUploadFile getFile(String name, String uploadPath, long maxPostSize, String encoding);

    public List<IUploadFile> getFiles(String uploadPath);
    /**
     * 校验码
     */
    public void renderCaptcha();
    public boolean validateCaptcha(String captchaParamName);

    public boolean isPOST();

    public boolean isGET();

    public boolean isPut();

    public boolean isDelete();

    public void render(IRender render);

    public void renderHtml(String html);

    public void renderJson(LambkitResult result);

    public void renderJson(Object data);

    public Map getRequestAttrs(String[] attrs);

    void renderError(int errorStatus, String msg);
}
